const { v4: uuidv4 } = require("uuid");
const MD5 = require("md5");
const moment = require("moment");
module.exports = {
  // 判断属性是否为空
  isDef(value) {
    return value !== undefined && value !== null && value !== "";
  },
  //md5加密
  md5(data) {
    return MD5(data);
  },
  // 获取uuid
  getUUID() {
    return uuidv4().replace(/-/g, "");
  },
  // 生成N位随机数
  getRandom(randomLength) {
    return Number(
      Math.random().toString().substr(2, randomLength) + Date.now()
    ).toString(36);
  },
  //深拷贝
  deepCopy(value) {
    // return loadsh.cloneDeep(value);
    return JSON.parse(JSON.stringify(value));
  },
  // 返回N位0
  zorroStr(len) {
    if (Number(len) <= 0) return "";
    let str = "";
    for (let i = 0; i < Number(len); i++) {
      str += "0";
    }
    return str;
  },
  // 对象数组去重
  uniqueArrayByObj(arr, key) {
    const obj = {};
    arr = arr.reduce(function (item, next) {
      obj[next[key]] ? "" : (obj[next[key]] = true && item.push(next));
      return item;
    }, []);
    return arr;
  },
  // 字符串数组去重
  uniqueArrayByString(arr) {
    return Array.from(new Set(arr));
  },
  /**
   * 将一维数组转换为树形
   * @param data 数据源
   * @param parentAcl 父id
   * @param p: 父属性
   * @param c  子属性
   */
  translateDataToTree(data, parentAcl = "-1", p = "parentId", c = "id") {
    let tree = [];
    let temp;

    data.forEach((item, index) => {
      if (data[index][p] == parentAcl) {
        let obj = data[index];
        temp = this.translateDataToTree(data, data[index][c], p, c);
        if (temp.length > 0) {
          obj.children = temp;
          let _num = 0;
          temp.map((item) => {
            _num += item.childrenNum;
          });
          obj.childrenNum = temp.length + _num;
        } else {
          obj.children = [];
          obj.childrenNum = 0;
        }
        // obj.isLeaf = obj.children.length > 0 ? false : true;
        tree.push(obj);
      }
    });
    return tree;
  },

  /**
   * @description 加法运算
   * @param arg1
   * @param arg2
   * @param decimalPlaces 保留小数位
   * @returns
   */
  numAdd(arg1, arg2, decimalPlaces = 2) {
    let r1, r2, m, c;
    try {
      r1 = arg1.toString().split(".")[1].length;
    } catch (e) {
      r1 = 0;
    }
    try {
      r2 = arg2.toString().split(".")[1].length;
    } catch (e) {
      r2 = 0;
    }
    c = Math.abs(r1 - r2);
    m = Math.pow(10, Math.max(r1, r2));
    if (c > 0) {
      const cm = Math.pow(10, c);
      if (r1 > r2) {
        arg1 = Number(arg1.toString().replace(".", ""));
        arg2 = Number(arg2.toString().replace(".", "")) * cm;
      } else {
        arg1 = Number(arg1.toString().replace(".", "")) * cm;
        arg2 = Number(arg2.toString().replace(".", ""));
      }
    } else {
      arg1 = Number(arg1.toString().replace(".", ""));
      arg2 = Number(arg2.toString().replace(".", ""));
    }
    return this.formatNumDecimals((arg1 + arg2) / m, decimalPlaces, true);
  },

  /**
   * @description 减法运算，避免数据相减小数点后产生多位数和计算精度损失。
   * @param num1 减数
   * @param num2 被减数
   * @param decimalPlaces 保留小数位
   */
  numSub(num1, num2, decimalPlaces = 2) {
    let baseNum, baseNum1, baseNum2;
    let precision; // 精度
    try {
      baseNum1 = num1.toString().split(".")[1].length;
    } catch (e) {
      baseNum1 = 0;
    }
    try {
      baseNum2 = num2.toString().split(".")[1].length;
    } catch (e) {
      baseNum2 = 0;
    }
    baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
    precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2;
    return this.formatNumDecimals(
      (num1 * baseNum - num2 * baseNum) / baseNum,
      decimalPlaces,
      true
    );
  },

  /**
   * 小数位数超过设定值，保留的小数位数
   *
   * @param maxNum保留的最大小数位数 | maxLength保留的小数位数 | forceFmt是否强制格式化
   */
  formatNumDecimals(num, maxLength, forceFmt) {
    num = Number(num);
    const x = String(num).indexOf(".") + 1; // 小数点的位置
    const y = String(num).length - x; // 小数的位数
    if (forceFmt || (y > 0 && y > maxLength)) {
      num = this.toFixed(num, maxLength);
    }
    return this.skipNaN(num);
  },

  skipNaN(val) {
    if (isNaN(Number(val))) {
      return val;
    } else {
      return Number(val);
    }
  },

  // 利用Round四舍五入
  toFixed(number, decimals) {
    let selftDecimals = "1";
    for (let i = 0; i < decimals; i++) {
      selftDecimals += "0";
    }
    return Math.round(number * Number(selftDecimals)) / Number(selftDecimals);
  },

  // 获取当前时间 20160106173721310
  getJSCurrTime() {
    let s = "";
    const d = new Date();
    s += d.getFullYear();
    const month = d.getMonth() + 1;
    if (month < 10) {
      s += "0" + month;
    } else {
      s += month;
    }
    const day = d.getDate();
    if (day < 10) {
      s += "0" + day;
    } else {
      s += day;
    }
    const hour = d.getHours();
    if (hour < 10) {
      s += "0" + hour;
    } else {
      s += hour;
    }
    const minu = d.getMinutes();
    if (minu < 10) {
      s += "0" + minu;
    } else {
      s += minu;
    }
    const sec = d.getSeconds();
    if (sec < 10) {
      s += "0" + sec;
    } else {
      s += sec;
    }
    s += d.getMilliseconds();
    return s;
  },

  /**
   * @description 创建流水单号
   * @param {IN|PI|OUT} type 流水类型 IN:积分 OUT:余额
   * @param txnType 交易类型 00： 转入 01：转出 07：奖励金 12：开卡手续费 13：充值手续费 14：在线充值 15：结算 17：消费手续费 18：退款
   */
  getSerialCode(type, txnType) {
    return `${type}${txnType}${this.getJSCurrTime()}`;
  },

  // 获取20位流水号
  getReqSysJnlNo(length) {
    const currTime = this.getJSCurrTime();
    const ranNum = length - currTime.length;
    const b = this.rndNum(ranNum);
    return `${currTime}${b}`;
  },

  // 获取当前时间
  getTime(format = "YYYY-MM-DD HH:mm:ss", date) {
    if (date) {
      return moment(date).format(format);
    } else {
      return moment(new Date()).format(format);
    }
  },

  rndNum(n) {
    let rnd = "";
    for (let i = 0; i < n; i++) rnd += Math.floor(Math.random() * 10);
    return rnd;
  },
};
